package org.flowable.flowablespringb3;

import org.flowable.engine.ProcessEngine;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@SpringBootTest
class FlowableTests01 {
    @Autowired
    private ProcessEngine processEngine;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private TaskService taskService;

    @Test
    void contextLoads() {
        System.out.println("processEngine: "+ processEngine);
        System.out.println("runtimeService: "+ runtimeService);
        System.out.println("repositoryService: "+ repositoryService);
        System.out.println("taskService: "+ taskService);
    }

    // 1. 部署流程
    // 部署完成后在 ACT_RE_DEPLOYMENT 表会见到一条 name=demoFlow1 的数据
    // 在 ACT_RE_PROCDEF 表中其 ACT_RE_PROCDEF.key = "processes/demoFlow1.bpmn20.xml" -> process.id
    @Test
    void deploy() {
        Deployment deployment = repositoryService
                // 创建一个部署
                .createDeployment()
                //部署的流程图, 可以一次添加多个流程图
                .addClasspathResource("processes/demoFlow1.bpmn20.xml")
                //这次部署的名字
                .name("demoFlow1")
                .deploy();
        // deployment: DeploymentEntity[id=d778e129-cf3e-11ef-8c0e-aae291037f7a, name=demoFlow1]
        System.out.println("deployment: "+ deployment);
    }

    // 通过 deploy() 方法返回的 deployment.id 查询 当此流程部署定义的id 或者 key
    // 例如返回内容为  deployment: DeploymentEntity[id=d778e129-cf3e-11ef-8c0e-aae291037f7a, name=demoFlow1]
    // 则下述 getProcessDefinition 方法 内 .deploymentId("d778e129-cf3e-11ef-8c0e-aae291037f7a")
    @Test
    void getProcessDefinition() {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId("d778e129-cf3e-11ef-8c0e-aae291037f7a")
                .latestVersion() // 获取最新版本
                .singleResult();

        System.out.println("pd.getDeploymentId() = " + processDefinition.getDeploymentId());
        System.out.println("pd.getId() = " + processDefinition.getId());
        System.out.println("pd.getKey() = " + processDefinition.getKey());
    }

    // 可以根据  processDefinition.getId() | processDefinition.getKey() 来启动一个流程
    // 例如上述 getProcessDefinition 方法返回的内容为
    // pd.getDeploymentId() = d778e129-cf3e-11ef-8c0e-aae291037f7a
    // pd.getId() = demo-flow1:2:d7bca0ec-cf3e-11ef-8c0e-aae291037f7a
    // pd.getKey() = demo-flow1
    @Test
    void startProcessByKey() {
        // 启动流程
        ProcessInstance processInstance = runtimeService.startProcessInstanceById("demo-flow1:2:d7bca0ec-cf3e-11ef-8c0e-aae291037f7a");
//        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("demoFlow1");
        System.out.println("processInstance: "+ processInstance);
    }

    // 此时进入流程一：固定值分配
    // 由于当前流程第一个 用户任务 分配的用户是 zhangsan
    @Test
    void queryTask1() {
        // 查询任务
        List<org.flowable.task.api.Task> tasks = taskService.createTaskQuery()
                .taskAssignee("zhangsan")
                .list();
        tasks.forEach(task -> {
            System.out.println("task.getId() = " + task.getId());
            System.out.println("task.getName() = " + task.getName());
            System.out.println("task.getAssignee() = "+ task.getAssignee());
        });
    }

    // 上述 返回
    // task.getId() = 84359d1d-cf3f-11ef-af22-aae291037f7a
    // task.getName() = 固定值分配
    // task.getAssignee() = zhangsan
    // 则可以直接完成任务，由于张三下个节点是 表达式赋值 需要定义一个map 将参数传到任务变量中
    // 此时的 ACT_RU_TASK 表 id=84359d1d-cf3f-11ef-af22-aae291037f7a 的记录
    @Test
    void completeTask1() {
        // 定义任务变量
        Map<String, Object> flowVariables = new HashMap<>();
        flowVariables.put("varUserName", "lisi");
        // 完成任务
        taskService.complete("84359d1d-cf3f-11ef-af22-aae291037f7a", flowVariables);
    }

    // 经过上述步骤 因为设置了 varUserName = lisi
    // 在 ACT_RU_TASK 表中 id=84359d1d-cf3f-11ef-af22-aae291037f7a 的记录 已经被删除
    // 并且创建了一条新的数据 其 assignee=lisi（此处的李四是上面步骤设置的） id=c35d1a65-cf40-11ef-a7fe-aae291037f7a
    // 在 ACT_RU_VARIABLE 表 name=varUserName text=lisi

    // 完成任务后 进入 用户任务： 表达式分配。
    @Test
    void completeTask2() {
        taskService.complete("c36a12b8-cf40-11ef-a7fe-aae291037f7a");
    }

    // 因为 后续节点任务是 方法调用分配 定义是
    //${userServer.getAssignee()}
    // 在项目中 org.flowable.flowablespringb3.demoflow1.service.UserServer.getAssignee() 方法 返回的还是list 所以现在
    // 最新的 ACT_RU_TASK 表中 assignee = lisi id=c4723e7d-cf41-11ef-bd33-aae291037f7a
    @Test
    void completeTask3() {
        taskService.complete("c4723e7d-cf41-11ef-bd33-aae291037f7a");
    }
    // 执行完 completeTask3 后， 后续 节点为监听器分配用户
    // org.flowable.flowablespringb3.demoflow1.listener.MyTaskListener 实现了 TaskListener 接口
    // 返回了 assignee = ange
    // 下面 执行完成后 则当前流程 结束
    @Test
    void completeTask4() {
        taskService.complete("475a83dd-cf42-11ef-ab5e-aae291037f7a");
    }
    // 流程结束后， ACT_RU_TASK 表清空
    // ACT_RU_VARIABLE 表清空

}
